import { expect } from '@jest/globals';
import * as fse from 'fs-extra';
import path from 'path';

import { initByFAJsEmptyApp, initExecuteCommand, runHvigor } from '../../common/common';
import { Probes } from '../../common/probes';
import { Constants, HOS_SIGNATURE_TEMPLATE, Tasks } from '../constants';
import { buildTest, checkSuccessful, configJsProject, createModule } from '../utils';

describe('mixed entry and feature test', () => {
  test.concurrent('Scenario 1 - Test build project - entry and feature not cross device', async () => {
    await initByFAJsEmptyApp(async (projectRoot) => {
      const commands = {
        mode: 'module',
        product: 'default',
        tasks: Tasks.ASSEMBLE_HAP,
      };

      createModule(projectRoot, 'application', ['wearable'], 'MainAbility', Constants.FEATURE);

      configJsProject(projectRoot,
        undefined,
        [{ moduleName: 'entry', deviceTypes: ['wearable'] }],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );

      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { rich: true });
      buildTest(projectRoot, 'application', 'default', Tasks.ASSEMBLE_HAP, {
        rich: true,
        moduleType: Constants.FEATURE
      });
    });
  });

  test.concurrent(
    'Scenario 2 - Test build project - entry cross device but feature not', async () => {
      await initByFAJsEmptyApp(async (projectRoot) => {
        const commands = {
          mode: 'module',
          product: 'default',
          tasks: Tasks.ASSEMBLE_HAP,
        };

        createModule(projectRoot, 'application', ['wearable'], 'MainAbility', Constants.FEATURE);

        configJsProject(projectRoot,
          undefined,
          [{ moduleName: 'entry', deviceTypes: ['wearable', 'liteWearable'] }],
          { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
        );

        checkSuccessful(projectRoot, commands);
        buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { mixed: true });
        buildTest(projectRoot, 'application', 'default', Tasks.ASSEMBLE_HAP,
          {
            rich: true,
            moduleType: Constants.FEATURE,
          });
      });
    });

  test.concurrent('Scenario 3 - Test build project - feature cross device but entry not', async () => {
    await initByFAJsEmptyApp(async (projectRoot) => {
      const commands = {
        mode: 'module',
        product: 'default',
        tasks: Tasks.ASSEMBLE_HAP,
      };

      createModule(projectRoot, 'application', ['wearable', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry', 'entry1']);
      createModule(projectRoot, 'entry1', ['phone'], 'MainAbility', Constants.ENTRY);

      configJsProject(projectRoot,
        undefined,
        [{ moduleName: 'entry', deviceTypes: ['wearable'] }],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );

      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { rich: true });

      buildTest(projectRoot, 'entry1', 'default', Tasks.ASSEMBLE_HAP, { rich: true });
      buildTest(projectRoot, 'application', 'default', Tasks.ASSEMBLE_HAP,
        {
          mixed: true,
          moduleType: Constants.FEATURE,
          entryModuleNames: ['entry', 'entry1'],
        });
    });
  });

  test.concurrent('Scenario 5 - Test build project - feature and entry both cross device', async () => {
    await initByFAJsEmptyApp(async (projectRoot) => {
      const commands = {
        mode: 'module',
        product: 'default',
        tasks: Tasks.ASSEMBLE_HAP,
      };

      createModule(projectRoot, 'feature1', ['wearable'], 'MainAbility',
        Constants.FEATURE, ['entry']);
      createModule(projectRoot, 'feature2', ['tablet', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry']);
      createModule(projectRoot, 'feature3', ['wearable', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry']);

      configJsProject(projectRoot,
        undefined,
        [{ moduleName: 'entry', deviceTypes: ['wearable', 'phone', 'tablet'] }],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );

      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { rich: true });

      buildTest(projectRoot, 'feature1', 'default', Tasks.ASSEMBLE_HAP,
        {
          rich: true,
          moduleType: Constants.FEATURE,
          entryModuleNames: ['entry'],
        }
      );
      buildTest(projectRoot, 'feature2', 'default', Tasks.ASSEMBLE_HAP,
        {
          rich: true,
          moduleType: Constants.FEATURE,
          entryModuleNames: ['entry'],
        }
      );
      buildTest(projectRoot, 'feature3', 'default', Tasks.ASSEMBLE_HAP,
        {
          rich: true,
          moduleType: Constants.FEATURE,
          entryModuleNames: ['entry'],
        }
      );
    });
  });

  test.concurrent('Scenario 6 - Test build project - abnormal scenarios - lite device', async () => {
    await initByFAJsEmptyApp(async (projectRoot) => {
      const commands = {
        mode: 'module',
        product: 'default',
        tasks: Tasks.ASSEMBLE_HAP,
      };

      createModule(projectRoot, 'feature', ['wearable'], 'MainAbility',
        Constants.FEATURE, ['entry']);

      const entryProbe = new Probes(projectRoot, path.resolve(projectRoot, 'entry'));
      const featureProbe = new Probes(projectRoot, path.resolve(projectRoot, 'feature'));

      fse.emptydirSync(entryProbe.getModuleBuildOutputPath());
      fse.emptydirSync(featureProbe.getModuleBuildOutputPath());

      configJsProject(projectRoot,
        undefined,
        [
          { moduleName: 'entry', deviceTypes: ['liteWearable', 'wearable'] },
        ],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );
      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { mixed: true });
      buildTest(projectRoot, 'feature', 'default', Tasks.ASSEMBLE_HAP,
        { rich: true, moduleType: Constants.FEATURE });
      fse.emptydirSync(entryProbe.getModuleBuildOutputPath());
      fse.emptydirSync(path.resolve(projectRoot, 'feature'));

      createModule(projectRoot, 'feature', ['wearable', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry']);
      configJsProject(projectRoot,
        undefined,
        [
          { moduleName: 'entry', deviceTypes: ['liteWearable', 'wearable'] },
        ],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );
      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { mixed: true });
      buildTest(projectRoot, 'feature', 'default', Tasks.ASSEMBLE_HAP,
        { rich: true, moduleType: Constants.FEATURE });
      fse.emptydirSync(entryProbe.getModuleBuildOutputPath());
      fse.emptydirSync(featureProbe.getModuleBuildOutputPath());

    });
  });

  test.concurrent('Scenario 7 - Test build project - abnormal scenarios - rich device', async () => {
    await initByFAJsEmptyApp(async (projectRoot) => {
      const commands = {
        mode: 'module',
        product: 'default',
        tasks: Tasks.ASSEMBLE_HAP,
      };

      createModule(projectRoot, 'feature', ['wearable', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry']);

      configJsProject(projectRoot,
        undefined,
        [
          { moduleName: 'entry', deviceTypes: ['wearable'] },
        ],
        {
          sdkVersion: 8,
          updateProducts: [
            {
              name: 'default',
              signingConfig: 'hos'
            }
          ]
        },
      );
      checkSuccessful(projectRoot, commands);
      buildTest(projectRoot, 'entry', 'default', Tasks.ASSEMBLE_HAP, { rich: true });
      buildTest(projectRoot, 'feature', 'default', Tasks.ASSEMBLE_HAP,
        {
          mixed: true,
          moduleType: Constants.FEATURE,
        });

      const entryProbe = new Probes(projectRoot, path.resolve(projectRoot, 'entry'));
      fse.emptydirSync(entryProbe.getModuleBuildOutputPath());
      fse.emptydirSync(path.resolve(projectRoot, 'feature'));

      createModule(projectRoot, 'feature', ['tablet', 'phone'], 'MainAbility',
        Constants.FEATURE, ['entry']);

      configJsProject(projectRoot,
        undefined,
        [
          { moduleName: 'entry', deviceTypes: ['wearable'] },
        ],
        { sdkVersion: 8, signConfig: HOS_SIGNATURE_TEMPLATE },
      );

      const result = runHvigor(projectRoot, initExecuteCommand(commands));
      expect(result.stderr.includes('The deviceType values (\'tablet,phone\') of default in the feature ' +
        'don\'t overlap that (\'wearable\') of default in the associated entry module'))
        .toBeTruthy();
    });
  });
});
